/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bungabungaball.gamestates;

import bungabungaball.Ball;
import bungabungaball.EndShowPowerUp;
import bungabungaball.GameObject;
import bungabungaball.GlobalSettings;
import static bungabungaball.GlobalSettings.gameModes.Client;
import static bungabungaball.GlobalSettings.gameModes.MultiPlayer;
import static bungabungaball.GlobalSettings.gameModes.Server;
import static bungabungaball.GlobalSettings.gameModes.SinglePlayer;
import bungabungaball.PlayerControl;
import bungabungaball.PowerUp;
import bungabungaball.StartShowPowerUp;
import bungabungaball.emitter.BungaParticleEmitter;
import bungabungaball.emitter.BungaParticleSystem;
import bungabungaball.player.CPU;
import bungabungaball.player.Human;
import bungabungaball.player.Network;
import bungabungaball.player.Player;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jbox2d.callbacks.ContactImpulse;
import org.jbox2d.callbacks.ContactListener;
import org.jbox2d.collision.Manifold;
import org.jbox2d.collision.shapes.MassData;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.FixtureDef;
import org.jbox2d.dynamics.World;
import org.jbox2d.dynamics.contacts.Contact;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
import org.newdawn.slick.openal.Audio;
import org.newdawn.slick.openal.AudioLoader;
import org.newdawn.slick.particles.ParticleSystem;
import org.newdawn.slick.util.ResourceLoader;

/**
 * *
 * The game state with the game
 *
 * @author Ingo Klose, Stephan Meyer, Sebastian Lehmann
 * @version 1.0
 */
public class GamePlay extends BasicGameState {

    /**
     * A litte implementation for 2D Vectory
     *
     * @param <T>
     */
    private class Vector<T extends Number> {

        public T x;
        public T y;
    }
    /**
     * The ID of the Game State
     */
    int stateID = 1;
    /**
     * The first Player
     */
    private Player p1;
    /**
     * The second Player
     */
    private Player p2;
    /**
     * The Ball
     */
    private Ball ball;
    /**
     * The physical World
     */
    private World world;
    /**
     * Happend a goal for player 1
     */
    private boolean goalForP1 = false;
    /**
     * Happend a goal for player 2
     */
    private boolean goalForP2 = false;
    /**
     * Number of goals for player 1 in the match
     */
    private Integer goalsP1 = 0;
    /**
     * Number of goals for player 2 in the match
     */
    private Integer goalsP2 = 0;
    /**
     * Counter for Replay
     */
    private Integer z = 0;
    /**
     * Integer for Replay
     */
    private int[][] pos = new int[6000][7];
    /**
     * Float for Replay
     */
    private float[][] rot = new float[6000][4];
    /**
     * The size of the Field
     */
    private Vector<Float> fieldSize;
    /**
     * The size of a goal
     */
    private float goalSize = 200;
    /**
     * The number of PowerUps that will be created
     */
    private int numberOfPowerUp = 0;
    /**
     * The number of PowerDowns that will be created
     */
    private int numberOfPowerDown = 0;
    /**
     * The Map
     */
    private int[][] map;
    /**
     * The color of the Background
     */
    private Color background;
    /**
     * The color of the lines
     */
    private Color lineColor;
    /**
     * The middlepoint of the game
     */
    private Vector<Float> mittelpunkt;
    /**
     * PlayerControl contends information about the currend game
     */
    private PlayerControl playerControl;
    /**
     * The time passed in the game
     */
    private int time = 0;
    /**
     * GoaldenGoal happens, if time if over and both player have the same number
     * of goals
     */
    private boolean goldenGoal = false;
    /**
     * The difference between the player and the middle point at begin of game
     */
    private int startX;
    /**
     * The Key Map sent by client player to the server
     */
    private boolean[] keyMapClientPlayer;
    /**
     * A audio with air horn sound after a goal
     */
    private Audio airHorn;
    /**
     * A audio with bungabunga at begin of the game
     */
    private Audio bungabunga;
    /**
     * A audio with a pop if the player is hitting something
     */
    private Audio pop;
    /**
     * There will be two particle systems, one for each player
     */
    private ParticleSystem[] particleSystem;
    /**
     * The BungaParticleSystem supports the visual effects
     */
    private BungaParticleSystem bungaParticleSystem;
    /**
     * The factor between physicle world and screen
     */
    private final int jBox2dFactor = GlobalSettings.jBox2dFactor;
    /**
     *
     * An image with chaos Arrows
     */
    private Image chaosImage;
    /**
     * A wall image
     */
    private Image wall1x1;

    /**
     *
     * Constructor, sets the default parameter and initialize objects
     *
     * @param stateID
     * @throws FileNotFoundException
     * @throws IOException
     */
    public GamePlay(int stateID) throws FileNotFoundException, IOException {
        this.stateID = stateID;
        fieldSize = new Vector<Float>();
        fieldSize.x = 0.0f;
        fieldSize.y = 0.0f;
        mittelpunkt = new Vector<Float>();
        mittelpunkt.x = 512.5f;
        mittelpunkt.y = 450f;
        this.map = new int[40][40];
        this.loadingMap(new File("maps\\defaultGamePlay.txt"));


    }

    /**
     * *
     * Load all sounds and images, set the Player to right position, create game
     * field
     *
     * @see #init(org.newdawn.slick.GameContainer,
     * org.newdawn.slick.state.StateBasedGame)
     * @param gc
     * @param sbg
     * @throws SlickException
     */
    @Override
    public void init(GameContainer gc, StateBasedGame sbg) throws SlickException {
        time=0;
        mittelpunkt.x = (float) gc.getWidth() / 2;
        mittelpunkt.y = (float) gc.getHeight() / 2;
        if (fieldSize.x < 450) {
            startX = 50;
        } else {
            startX = (int) Math.round(mittelpunkt.x / 1.8);
        }

        createPlayer();

        chaosImage = new Image("\\img\\chaosArrow.png");
        wall1x1 = new Image("\\img\\wall_yellow1x1.png");

        playerControl = new PlayerControl(gc, mittelpunkt.x, mittelpunkt.y, fieldSize.x, fieldSize.y, goalSize);
        try {
            airHorn = AudioLoader.getAudio("WAV", ResourceLoader.getResourceAsStream("sound/airHorn.wav"));
            bungabunga = AudioLoader.getAudio("WAV", ResourceLoader.getResourceAsStream("sound/bungabunga.wav"));
            pop = AudioLoader.getAudio("WAV", ResourceLoader.getResourceAsStream("sound/pop.wav"));
        } catch (IOException ex) {
            Logger.getLogger(GamePlay.class.getName()).log(Level.SEVERE, null, ex);
        }

        Vec2 gravity = new Vec2(0.0f, 0.0f);
        boolean doSleep = true;
        world = new World(gravity, doSleep);
        world.setContactListener(new ContactListener() {
            @Override
            public void beginContact(Contact cntct) {
            }

            @Override
            public void endContact(Contact cntct) {
            }

            @Override
            public void preSolve(Contact cntct, Manifold mnfld) {
                if (GlobalSettings.currentGameMode != GlobalSettings.gameModes.Client) {
                    // Prüfen ob ein Spieler gegen ein PowerUp gefahren ist
                    if (cntct.getFixtureA().getUserData() instanceof Integer && (cntct.getFixtureB().getUserData() == "p1" || cntct.getFixtureB().getUserData() == "p2")) {
                        if (GlobalSettings.currentGameMode != GlobalSettings.gameModes.Client) {
                            int i = (Integer) cntct.getFixtureA().getUserData();
                            GlobalSettings.powerUp[i].setShow(false);
                            world.destroyBody(GlobalSettings.powerUp[i].getBody());
                            GlobalSettings.powerUp[i].setHideSecond(0);
                            GlobalSettings.powerUp[i].getBody().setActive(false);
                            if (cntct.getFixtureA().getUserData() == "p1" || cntct.getFixtureB().getUserData() != "p1") {
                                particleSystem[1].addEmitter(new bungabungaball.emitter.PowerUp());
                                p2.setSpeed(p2.getSpeed() * GlobalSettings.powerUp[i].getNewSpeed());
                                p2.controlMode = GlobalSettings.powerUp[i].getControlMode();
                                MassData newMass = new MassData();
                                newMass.mass = p2.getBody().getMass() * GlobalSettings.powerUp[i].getNewMass();
                                p2.getBody().setMassData(newMass);
                            }
                            if (cntct.getFixtureA().getUserData() == "p2" || cntct.getFixtureB().getUserData() != "p2") {
                                particleSystem[0].addEmitter(new bungabungaball.emitter.PowerUp());
                                p1.setSpeed(p1.getSpeed() * GlobalSettings.powerUp[i].getNewSpeed());
                                p1.controlMode = GlobalSettings.powerUp[i].getControlMode();
                                MassData newMass = new MassData();
                                newMass.mass = p1.getBody().getMass() * GlobalSettings.powerUp[i].getNewMass();
                                p1.getBody().setMassData(newMass);
                            }
                        }
                    }
                    if (cntct.getFixtureB().getUserData() instanceof Integer && (cntct.getFixtureA().getUserData() == "p1" || cntct.getFixtureA().getUserData() == "p2")) {
                        if (GlobalSettings.currentGameMode != GlobalSettings.gameModes.Client) {
                            int i = (Integer) cntct.getFixtureB().getUserData();
                            GlobalSettings.powerUp[i].setShow(false);
                            world.destroyBody(GlobalSettings.powerUp[i].getBody());
                            GlobalSettings.powerUp[i].setHideSecond(0);
                            GlobalSettings.powerUp[i].getBody().setActive(false);
                            if (cntct.getFixtureA().getUserData() == "p1" || cntct.getFixtureB().getUserData() == "p1") {
                                particleSystem[0].addEmitter(new bungabungaball.emitter.PowerUp());
                                p1.setSpeed(p1.getSpeed() * GlobalSettings.powerUp[i].getNewSpeed());
                                p1.controlMode = GlobalSettings.powerUp[i].getControlMode();
                                MassData newMass = new MassData();
                                newMass.mass = p1.getBody().getMass() * GlobalSettings.powerUp[i].getNewMass();
                                p1.getBody().setMassData(newMass);
                            }
                            if (cntct.getFixtureA().getUserData() == "p2" || cntct.getFixtureB().getUserData() == "p2") {
                                particleSystem[1].addEmitter(new bungabungaball.emitter.PowerUp());
                                p2.setSpeed(p2.getSpeed() * GlobalSettings.powerUp[i].getNewSpeed());
                                p2.controlMode = GlobalSettings.powerUp[i].getControlMode();
                                MassData newMass = new MassData();
                                newMass.mass = p2.getBody().getMass() * GlobalSettings.powerUp[i].getNewMass();
                                p2.getBody().setMassData(newMass);
                            }
                        }
                    }

                    // Prüfen ob ein Spieler gegen die Wand oder einen anderen Spieler gefahren ist
                    if ((cntct.getFixtureA().getUserData() == "p1" && cntct.getFixtureB().getUserData() != "ball" && !(cntct.getFixtureB().getUserData() instanceof Integer))
                            || (cntct.getFixtureB().getUserData() == "p1" && cntct.getFixtureA().getUserData() != "ball" && !(cntct.getFixtureA().getUserData() instanceof Integer))) {
                        particleSystem[0].addEmitter(new bungabungaball.emitter.Dust());
                    }
                    if ((cntct.getFixtureA().getUserData() == "p2" && cntct.getFixtureB().getUserData() != "ball" && !(cntct.getFixtureB().getUserData() instanceof Integer))
                            || (cntct.getFixtureB().getUserData() == "p2" && cntct.getFixtureA().getUserData() != "ball" && !(cntct.getFixtureA().getUserData() instanceof Integer))) {
                        particleSystem[1].addEmitter(new bungabungaball.emitter.Dust());
                    }
                    if ((cntct.getFixtureA().getUserData() == "p1" && cntct.getFixtureB().getUserData() != "ball")
                            || (cntct.getFixtureA().getUserData() == "p2" && cntct.getFixtureB().getUserData() != "ball")
                            || (cntct.getFixtureB().getUserData() == "p1" && cntct.getFixtureA().getUserData() != "ball")
                            || (cntct.getFixtureB().getUserData() == "p2" && cntct.getFixtureA().getUserData() != "ball")) {
                        if (GlobalSettings.sound) {
                            pop.playAsSoundEffect(1.0f, 1.0f, false);
                        }
                    }
                }
            }

            @Override
            public void postSolve(Contact cntct, ContactImpulse ci) {
            }
        });
        //map = new int[40][40];

//        try {
//            this.loadingMap(new File("maps\\defaultGamePlay.txt"));
//        } catch (FileNotFoundException ex) {
//            Logger.getLogger(GamePlay.class.getName()).log(Level.SEVERE, null, ex);
//        } catch (IOException ex) {
//            Logger.getLogger(GamePlay.class.getName()).log(Level.SEVERE, null, ex);
//        }

        ball = new bungabungaball.Ball(mittelpunkt.x.intValue(), mittelpunkt.y.intValue(), new Image("\\img\\ball.png"));

        this.createWalls(fieldSize.x, fieldSize.y, this.goalSize);
        this.createHindernis();

        p1.setBody(world.createBody(p1.getBodyDef()));
        p1.getBody().createFixture(p1.getFixtureDef());

        p2.setBody(world.createBody(p2.getBodyDef()));
        p2.getBody().createFixture(p2.getFixtureDef());



        //PlayerControl erzeugen
        playerControl = new PlayerControl(gc, mittelpunkt.x, mittelpunkt.y, fieldSize.x, fieldSize.y, goalSize);

        ball.setBody(world.createBody(ball.getBodyDef()));
        ball.getBody().createFixture(ball.getFixtureDef());

        z = 0;
        this.kickoffBall();

        particleSystem = new ParticleSystem[2];
        particleSystem[0] = new ParticleSystem(new Image("\\img\\green.png"));
        particleSystem[1] = new ParticleSystem(new Image("\\img\\green.png"));

        bungaParticleSystem = new BungaParticleSystem("\\img\\green.png");

        if (GlobalSettings.currentGameMode != GlobalSettings.gameModes.Client) {
            createPowerUpAndPowerDown();
        } else {
            createPowerUpAndPowerDownEmpty();
        }
 

    }

    /**
     * Handels any input
     *
     * @param gc
     * @param sbg
     * @param delta
     * @throws SlickException
     */
    @Override
    public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException {

        Input input = gc.getInput();


        //Check for the end of the game/goldengoal
        time += delta;
        if (time >= GlobalSettings.gameRunningTime && goalsP1 == goalsP2) {
            goldenGoal = true;
        } else if (time >= GlobalSettings.gameRunningTime && goalsP1 > goalsP2) {
            GlobalSettings.winner = 1;
            sbg.enterState(bungabungaball.BungaBungaBall.GAMEENDPLAYSTATE);
        } else if (time >= GlobalSettings.gameRunningTime && goalsP2 > goalsP1) {
            GlobalSettings.winner = 2;
            sbg.enterState(bungabungaball.BungaBungaBall.GAMEENDPLAYSTATE);
        }




        if (GlobalSettings.currentGameMode == GlobalSettings.gameModes.Replay) {
            
            for(int j = 0; j < 6000; j++) {
                if(time == 0) {
                    
                    p1.x = pos[0][1];
                    p1.y = pos[0][2];
                    p2.x = pos[0][3];
                    p2.y = pos[0][4];
                    ball.x = pos[0][5];
                    ball.y = pos[0][6];

                    p1.setRotation(rot[0][0]);
                    p2.setRotation(rot[0][1]);
                    p1.setSpeed(rot[0][2]);
                    p2.setSpeed(rot[0][3]);
                }else if(time > pos[j][0] && j < 5999 &&time <= pos[j+1][0]){
                    
                    p1.x = pos[j][1];
                    p1.y = pos[j][2];
                    p2.x = pos[j][3];
                    p2.y = pos[j][4];
                    ball.x = pos[j][5];
                    ball.y = pos[j][6];

                    p1.setRotation(rot[j][0]);
                    p2.setRotation(rot[j][1]);
                    p1.setSpeed(rot[j][2]);
                    p2.setSpeed(rot[j][3]);
                }
            }
//            p1.x = pos[z][1];
//            p1.y = pos[z][2];
//            p2.x = pos[z][3];
//            p2.y = pos[z][4];
//            ball.x = pos[z][5];
//            ball.y = pos[z][6];
//
//            p1.setRotation(rot[z][0]);
//            p2.setRotation(rot[z][1]);
//            p1.setSpeed(rot[z][2]);
//            p2.setSpeed(rot[z][3]);
            z++;

            if (input.isKeyDown(Input.KEY_ESCAPE)) {
                try {
                    Thread.sleep(250);
                } catch (InterruptedException ex) {
                    Logger.getLogger(GamePlay.class.getName()).log(Level.SEVERE, null, ex);
                }
                sbg.enterState(bungabungaball.BungaBungaBall.MAINMENUSTATE);
            }
        } else {
            // Go the World a Step forther
            float timeStep = 0.f;
            timeStep = 1.0f / gc.getFPS();
            int velocityIterations = 6;
            int positionIterations = 2;
            world.step(timeStep, velocityIterations, positionIterations);
            // Update the new Positions on the Objects
            if (GlobalSettings.currentGameMode != GlobalSettings.gameModes.Client) {
                updatePosition(p1.getBody(), p1, -35.0f);
                updatePosition(p2.getBody(), p2, -35.0f);
                updatePosition(ball.getBody(), ball, -10.0f);
            }


            playerControl.setBallPosition(ball.x, ball.y);

            // add Friction on the Ball
            makeFriction(ball.getBody());

            // Handle the Input

            try {
                p1.move(playerControl, delta, p1.getBody(), keyMapClientPlayer);
            } catch (Exception ex) {
                Logger.getLogger(GamePlay.class.getName()).log(Level.SEVERE, null, ex);
            }
            try {
                p2.move(playerControl, delta, p2.getBody(), keyMapClientPlayer);
            } catch (Exception ex) {
                Logger.getLogger(GamePlay.class.getName()).log(Level.SEVERE, null, ex);
            }

            //Bewegung
            switch (GlobalSettings.currentGameMode) {
                case Server:
                    int[] positions = {
                        p1.x,
                        p1.y,
                        p2.x,
                        p2.y,
                        ball.x,
                        ball.y
                    };
                    PlayerControl.server.sendToAllTCP(positions);
                    float[] playerRotations = {
                        p1.getRotation(),
                        p2.getRotation()
                    };
                    PlayerControl.server.sendToAllTCP(playerRotations);
                    float[][] test = {
                        {p1.getBody().getLinearVelocity().x, p1.getBody().getLinearVelocity().y},
                        {p2.getBody().getLinearVelocity().x, p2.getBody().getLinearVelocity().y},
                        {ball.getBody().getLinearVelocity().x, ball.getBody().getLinearVelocity().y},};
                    PlayerControl.server.sendToAllTCP(test);
                    break;
                case Client:
                    //PlayerControl.client.sendTCP(p1);
                    boolean[] keys = {
                        input.isKeyDown(GlobalSettings.keyMapPlayer1[0]),
                        input.isKeyDown(GlobalSettings.keyMapPlayer1[1]),
                        input.isKeyDown(GlobalSettings.keyMapPlayer1[2]),
                        input.isKeyDown(GlobalSettings.keyMapPlayer1[3])
                    };
                    PlayerControl.client.sendTCP(keys);
                    break;
            }

            if (input.isKeyDown(Input.KEY_ESCAPE)) {
                try {
                    Thread.sleep(250);
                } catch (InterruptedException ex) {
                    Logger.getLogger(GamePlay.class.getName()).log(Level.SEVERE, null, ex);
                }
                try {
                    this.loadingMap(new File("maps\\defaultGamePlay.txt"));
                } catch (FileNotFoundException ex) {
                    Logger.getLogger(GamePlay.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IOException ex) {
                    Logger.getLogger(GamePlay.class.getName()).log(Level.SEVERE, null, ex);
                }
                GlobalSettings.gameRunningTime = 120000;
                GlobalSettings.discoMode = false;
                GlobalSettings.sound = true;
                sbg.enterState(bungabungaball.BungaBungaBall.MAINMENUSTATE);
            }

            if (input.isKeyDown(Input.KEY_SPACE)) {
                // bungaParticleSystem.addEmitter(new BungaParticleEmitter(p1.getRotation(), p1.x, p1.y));
            }

            //bungaParticleSystem.setRotation(p1.getRotation());

            if (p1.getSpeed() > GlobalSettings.playerSpeed) {
                bungaParticleSystem.addEmitter(new BungaParticleEmitter(p1.getRotation(), p1.x, p1.y));
            }


            if (p2.getSpeed() > GlobalSettings.playerSpeed) {
                bungaParticleSystem.addEmitter(new BungaParticleEmitter(p2.getRotation(), p2.x, p2.y));
            }

            

            pos[z][0] = time;
            pos[z][1] = p1.x;
            pos[z][2] = p1.y;
            pos[z][3] = p2.x;
            pos[z][4] = p2.y;
            pos[z][5] = ball.x;
            pos[z][6] = ball.y;

            rot[z][0] = p1.getRotation();
            rot[z][1] = p2.getRotation();
            rot[z][2] = p1.getSpeed();
            rot[z][3] = p2.getSpeed();

            z++;

        }

        int seconds = (int) time / 1000;
        int i = 0;
        for (PowerUp m : GlobalSettings.powerUp) {
            if (seconds >= m.getShowSecond() && seconds <= m.getHideSecond()) {
                    
                if (m.getShow() == false) {
                    m.setShow(true);

                    BodyDef bd = new BodyDef();
                    bd.position.set(m.getX() / jBox2dFactor, m.getY() / jBox2dFactor);
                    bd.type = BodyType.STATIC;

                    PolygonShape shape = new PolygonShape();
                    shape.setAsBox(10 / jBox2dFactor, 10 / jBox2dFactor);
                    FixtureDef fdef = new FixtureDef();
                    fdef.shape = shape;

                    fdef.userData = i;

                    Body b = world.createBody(bd);
                    b.createFixture(fdef);
                    m.setBodyDef(bd);
                    m.setBody(b);
                }
            } else if (m.getShow()) {
                m.setShow(false);
                if (GlobalSettings.currentGameMode != GlobalSettings.gameModes.Replay) {
                    world.destroyBody(m.getBody());
                }
                
                m.getBody().setActive(false);
            }
            ++i;
        }
        
        this.proofGoal();

        //Tor gefallen; Spielstand incrementieren; Anstoß/Spielende bei GoldenGoal
        if (goalForP1) {
            goalsP1++;
            if (goldenGoal) {
                GlobalSettings.winner = 1;
                sbg.enterState(bungabungaball.BungaBungaBall.GAMEENDPLAYSTATE);
            } else {
                this.kickoff();
            }
        }
        if (goalForP2) {
            goalsP2++;
            if (goldenGoal) {
                GlobalSettings.winner = 2;
                sbg.enterState(bungabungaball.BungaBungaBall.GAMEENDPLAYSTATE);
            } else {
                this.kickoff();
            }
        }
        particleSystem[0].update(delta);
        particleSystem[1].update(delta);

        bungaParticleSystem.update(delta);
    }

    /**
     * *
     * Renders the game
     *
     * @param gc
     * @param sbg
     * @param g
     * @throws SlickException
     */
    @Override
    public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException {
        g.setAntiAlias(true);
        g.setBackground(background);
        g.setFont(MainMenu.font);

        // Wenn DiscoMode
        if (GlobalSettings.discoMode) {
            for (int i = 0; i < 41; ++i) {
                for (int j = 0; j < 32; ++j) {
                    g.setColor(new Color((int) (Math.random() * 255 + 1), (int) (Math.random() * 255 + 1), (int) (Math.random() * 255 + 1)));
                    g.fillRect(i * 25, 75 + j * 25, 25, 25);
                }
            }
        }

        this.drawField(g, fieldSize.x, fieldSize.y, this.goalSize);

        particleSystem[0].render(p1.x + 35, p1.y + 35);
        particleSystem[1].render(p2.x + 35, p2.y + 35);

        bungaParticleSystem.render(0, 0);

        p1.draw(g);
        p2.draw(g);
        ball.draw(g);

        //Provisorischer Spielstand
        String tor1 = goalsP1.toString();
        String tor2 = goalsP2.toString();
        String Spielstand = "Spielstand: Roter Spieler " + tor1 + ":" + tor2 + " Blauer Spieler";
        int textLength = gc.getDefaultFont().getWidth(Spielstand);
        g.setColor(Color.green);
        g.drawString(Spielstand, GlobalSettings.windowSizeX - 10 - textLength, 10);
        for (PowerUp m : GlobalSettings.powerUp) {
            if (m.getShow()) {
                m.draw(g);
            }
        }

        drawSpeedometer(g, 10, GlobalSettings.windowSizeY - 75, 150, 0, GlobalSettings.playerMaxSpeed, p1.getSpeed());
        drawSpeedometer(g, GlobalSettings.windowSizeX - 10 - 150, GlobalSettings.windowSizeY - 75, 150, 0, GlobalSettings.playerMaxSpeed, p2.getSpeed());

        if (p1.controlMode == GlobalSettings.ControlMode.Dificult) {
            g.drawImage(chaosImage, 175, GlobalSettings.windowSizeY - 75);
        }
        if (p2.controlMode == GlobalSettings.ControlMode.Dificult) {
            g.drawImage(chaosImage, GlobalSettings.windowSizeX - 245, GlobalSettings.windowSizeY - 75);
        }
        drawTime(g, 150, 5, 150, 25, time);

        this.drawHindernis(g);
    }

    /**
     * Draw a baricade graphically
     *
     * @param g
     */
    public void drawHindernis(Graphics g) {

        float startX = 104;
        for (int i = 0; i < 40; i++) {
            for (int j = 0; j < 40; j++) {
                if (map[i][j] == 1) {
                    g.drawImage(wall1x1, startX + (i * 24) + 1, (j * 24) + 1);
                    //this.addWall(startX + (i * 24) + 1, (j * 24) + 1, 24, 24);
                }
            }
        }
    }

    /**
     * Create a baricade physically
     *
     */
    public void createHindernis() {
        float startX = 104;
        for (int i = 0; i < 40; i++) {
            for (int j = 0; j < 40; j++) {
                if (map[i][j] == 1) {
                    this.addWall(startX + (i * 24) + 13, (j * 24) + 13, 12, 12);
                }
            }
        }
    }

    /**
     * *
     * Add a wall to the World at position ({
     *
     * @param x
     * @param y
     * @param w
     * @param h
     */
    private void addWall(float x, float y, float w, float h) {
        BodyDef wand = new BodyDef();
        wand.position.set(x / jBox2dFactor, y / jBox2dFactor);
        wand.type = BodyType.STATIC;

        PolygonShape shape = new PolygonShape();
        shape.setAsBox(w / jBox2dFactor, h / jBox2dFactor);
        FixtureDef fdef = new FixtureDef();
        fdef.shape = shape;
        Body b = world.createBody(wand);
        b.createFixture(fdef);
    }

    /**
     * *
     * create a rundom integer between {
     *
     * @param low
     * @param high
     * @return The random integer
     */
    private int random(int low, int high) {
        high++;
        return (int) (Math.random() * (high - low) + low);
    }

    /**
     * *
     * Add a edge to the world at position ({
     *
     * @param x
     * @param y
     * @param w
     * @param h
     */
    private void addStaticEgde(float x, float y, float w, float h) {
        BodyDef edge = new BodyDef();
        edge.position.set(x / jBox2dFactor, y / jBox2dFactor);
        edge.type = BodyType.STATIC;

        PolygonShape shape = new PolygonShape();
        Vec2[] vec = new Vec2[3];
        if (w > 0.f) {
            if (h > 0.f) {
                vec[0] = new Vec2(0, 0);
                vec[1] = new Vec2(h / jBox2dFactor, 0);
                vec[2] = new Vec2(0, w / jBox2dFactor);
            } else {
                vec[0] = new Vec2(h / jBox2dFactor, 0);
                vec[1] = new Vec2(0, 0);
                vec[2] = new Vec2(0, w / jBox2dFactor);
            }
        } else {
            if (h > 0.f) {
                vec[0] = new Vec2(h / jBox2dFactor, 0);
                vec[1] = new Vec2(0, 0);
                vec[2] = new Vec2(0, w / jBox2dFactor);
            } else {
                vec[0] = new Vec2(0, 0);
                vec[1] = new Vec2(h / jBox2dFactor, 0);
                vec[2] = new Vec2(0, w / jBox2dFactor);
            }
        }

        shape.set(vec, 3);

        FixtureDef fdef = new FixtureDef();
        fdef.shape = shape;

        Body b = world.createBody(edge);
        b.createFixture(fdef);
    }

    /**
     * *
     * Get the ID of the state
     *
     * @return the ID of the state
     */
    @Override
    public int getID() {
        return stateID;
    }

    /**
     * *
     * Called, when the game state is entered.
     *
     * @param gc
     * @param sbg
     * @throws SlickException
     * @see #init(org.newdawn.slick.GameContainer,
     * org.newdawn.slick.state.StateBasedGame)
     */
    @Override
    public void enter(GameContainer gc, StateBasedGame sbg) throws SlickException {
        init(gc, sbg);
        if (GlobalSettings.sound) {
            bungabunga.playAsSoundEffect(1.0f, 1.0f, false);
        }

    }

    /**
     * Create PowerUp and PowerDown, sothat they are never shown (for Client
     * Network)
     *
     * @throws SlickException
     */
    private void createPowerUpAndPowerDownEmpty() throws SlickException {
        int numberUp = (int) (numberOfPowerUp / 100.0f * 100.0f);
        int numberDown = (int) (numberOfPowerDown / 100.0f * 100.0f);
        GlobalSettings.powerUp = new PowerUp[numberUp + numberDown];
        for (int i = 0; i < numberUp + numberDown; i++) {
            GlobalSettings.powerUp[i] = new PowerUp(new Image("\\img\\box.png"));
            GlobalSettings.powerUp[i].setShowSecond(0);
            GlobalSettings.powerUp[i].setHideSecond(0);
            GlobalSettings.powerUp[i].setPosition(new Vec2(0, 0));
            GlobalSettings.powerUp[i].initPowerDown();
            GlobalSettings.powerUp[i].setNumber(i);
        }
        
    }

    /**
     * *
     * Create the PowerUps and PowerDowns
     *
     * @throws SlickException
     */
    private void createPowerUpAndPowerDown() throws SlickException {
        if (GlobalSettings.currentGameMode != GlobalSettings.gameModes.Replay) {
            int numberUp = (int) (numberOfPowerUp / 100.0f * 100.0f);
            int numberDown = (int) (numberOfPowerDown / 100.0f * 100.0f);

            float poitLeftUpX = mittelpunkt.x - (fieldSize.x / 2) + 25;
            float poitLeftUpY = mittelpunkt.y - (fieldSize.y / 2) + 25;
            float poitRightDownX = mittelpunkt.x + (fieldSize.x / 2) - 25;
            float poitRightDownY = mittelpunkt.y + (fieldSize.y / 2) - 25;

            GlobalSettings.powerUp = new PowerUp[numberUp + numberDown];
            // create PowerUp
            for (int i = 0; i < numberUp; i++) {

                int timeCreate = random(0, GlobalSettings.gameRunningTime / 1000);
                GlobalSettings.powerUp[i] = new PowerUp(new Image("\\img\\box.png"));
                GlobalSettings.powerUp[i].setShowSecond(timeCreate);
                GlobalSettings.powerUp[i].setHideSecond(timeCreate + 10);
                GlobalSettings.powerUp[i].setPosition(new Vec2(random((int) poitLeftUpX, (int) poitRightDownX), random((int) poitLeftUpY, (int) poitRightDownY)));
                GlobalSettings.powerUp[i].initPowerUp();
                GlobalSettings.powerUp[i].setNumber(i);
                
            }
            // create PowerDown
            for (int i = numberUp; i < numberUp + numberDown; i++) {

                int timeCreate = random(0, GlobalSettings.gameRunningTime / 1000);
                GlobalSettings.powerUp[i] = new PowerUp(new Image("\\img\\box.png"));
                GlobalSettings.powerUp[i].setShowSecond(timeCreate);
                GlobalSettings.powerUp[i].setHideSecond(timeCreate + 10);
                GlobalSettings.powerUp[i].setPosition(new Vec2(random((int) poitLeftUpX, (int) poitRightDownX), random((int) poitLeftUpY, (int) poitRightDownY)));
                GlobalSettings.powerUp[i].initPowerDown();
                GlobalSettings.powerUp[i].setNumber(i);
                
            }
        }else{
            for(PowerUp m: GlobalSettings.powerUp) {
                PowerUp n = new PowerUp(new Image("\\img\\box.png"));
                int t = m.getShowSecond();
                n.setShowSecond(t);
                n.setHideSecond(t + 10);
                n.setPosition(new Vec2(m.getPosition().x, m.getPosition().y));
                n.initPowerDown();
                n.setNumber(m.getNumber());
                n.setShow(false);
                m = n;
                
            }
        }
        
    }

    /**
     * *
     * Create the Player
     *
     * @throws SlickException
     */
    private void createPlayer() throws SlickException {

        time = 0;
        goalsP1 = 0;
        goalsP2 = 0;
        goldenGoal = false;


        switch (GlobalSettings.currentGameMode) {
            case SinglePlayer:

                p1 = new Human((int) (mittelpunkt.x - startX), (int) mittelpunkt.y.intValue(), new Image("\\img\\player1.png"), world);
                p1.setRotation(+90);
                p2 = new CPU((int) (mittelpunkt.x + startX), (int) mittelpunkt.y.intValue(), new Image("\\img\\player2.png"), world);
                p2.setRotation(-90);
                break;
            case MultiPlayer:
                p1 = new Human((int) (mittelpunkt.x - startX), (int) mittelpunkt.y.intValue(), new Image("\\img\\player1.png"), world);
                p1.setRotation(90);
                p2 = new Human((int) (mittelpunkt.x + startX), (int) mittelpunkt.y.intValue(), new Image("\\img\\player2.png"), world);
                p2.setRotation(-90);
                p2.setKeyMap(GlobalSettings.keyMapPlayer2);
                break;
            case Server:
                p1 = new Human((int) (mittelpunkt.x - startX), (int) mittelpunkt.y.intValue(), new Image("\\img\\player1.png"), world);
                p1.setRotation(90);
                p2 = new Network((int) (mittelpunkt.x + startX), (int) mittelpunkt.y.intValue(), new Image("\\img\\player2.png"), world);
                p2.setRotation(-90);
                PlayerControl.server.addListener(new Listener() {
                    @Override
                    public void received(Connection connection, Object object) {
                        if (object instanceof boolean[]) {
                            boolean[] request = (boolean[]) object;
                            keyMapClientPlayer = request;
                        }
                    }
                });
                break;
            case Client:
                p1 = new Network((int) (mittelpunkt.x - startX), (int) mittelpunkt.y.intValue(), new Image("\\img\\player1.png"), world);
                p1.setRotation(90);
                p2 = new Human((int) (mittelpunkt.x + startX), (int) mittelpunkt.y.intValue(), new Image("\\img\\player2.png"), world);
                p2.setRotation(-90);
                p2.setKeyMap(GlobalSettings.keyMapPlayer1);
                PlayerControl.client.addListener(new Listener() {
                    @Override
                    public void received(Connection connection, Object object) {
                        if (object instanceof int[]) {
                            int[] request = (int[]) object;
                            for(int i: request) {
                                System.out.println(i);
                            }
                            p1.x = request[0];
                            p1.y = request[1];
                            p2.x = request[2];
                            p2.y = request[3];
                            ball.x = request[4];
                            ball.y = request[5];
                            p1.getBody().setTransform(new Vec2(request[0] / jBox2dFactor, request[1] / jBox2dFactor), p1.getBody().getAngle());
                            p2.getBody().setTransform(new Vec2(request[2] / jBox2dFactor, request[3] / jBox2dFactor), p2.getBody().getAngle());
                            ball.getBody().setTransform(new Vec2(request[4] / jBox2dFactor, request[5] / jBox2dFactor), ball.getBody().getAngle());

                        } else if (object instanceof float[]) {
                            float[] request = (float[]) object;
                            p1.setRotation(request[0]);
                            p2.setRotation(request[1]);
                        } else if (object instanceof float[][]) {
                            float[][] request = (float[][]) object;
                            p1.getBody().setLinearVelocity(new Vec2(request[0][0], request[0][1]));
                            p2.getBody().setLinearVelocity(new Vec2(request[1][0], request[1][1]));
                            ball.getBody().setLinearVelocity(new Vec2(request[2][0], request[2][1]));
                        } else if (object instanceof StartShowPowerUp) {
                            StartShowPowerUp s = (StartShowPowerUp) object;
                            GlobalSettings.powerUp[s.number].setShowSecond(s.start);
                            GlobalSettings.powerUp[s.number].setHideSecond(s.end);
                            GlobalSettings.powerUp[s.number].setPosition(new Vec2(s.x, s.y));
                        } else if (object instanceof EndShowPowerUp) {
                            EndShowPowerUp e = (EndShowPowerUp) object;
                            GlobalSettings.powerUp[e.number].setShow(false);
                            GlobalSettings.powerUp[e.number].setHideSecond(0);
                        }
                    }
                });
                break;
        }
        p1.getFixtureDef().userData = "p1";
        p2.getFixtureDef().userData = "p2";
    }

    /**
     * Draw a Speedometer
     *
     * @param g The graphics
     * @param x Position Top Left on Screen
     * @param y Position Top Left on Screen
     * @param w The Size of the Speedometer
     * @param min The lowest value on the speedometer
     * @param max The highest value on the speedometer
     * @param current The value on the speedometer
     */
    private void drawSpeedometer(Graphics g, int x, int y, int w, float min, float max, float current) {
        int h = w / 2;
        g.setColor(new Color(255f, 255f, 255f, 0.5f));
        g.fillArc(x, y, w, h * 2, 180, 360);
        g.setColor(new Color(255f, 255f, 255f, 1f));
        g.fillArc(x + 10, y + 10, w - 20, h * 2 - 20, 180, 360);

        g.setColor(Color.blue);
        g.drawString((new Float(min)).toString(), x, y + h - g.getFont().getLineHeight());
        String maxString = (new Float(max)).toString();
        g.drawString(maxString, x + w - g.getFont().getWidth(maxString), y + h - g.getFont().getLineHeight());
        String middleString = (new Float((max + min) / 2)).toString();
        g.drawString(middleString, x + w / 2 - g.getFont().getWidth(middleString) / 2, y);
        float percent = (current) / ((max) - (min));
        float alpha = -180 * percent - 90;

        g.setColor(Color.red);
        int startPointX = x + w / 2;
        int startPointY = y + w / 2;
        g.fillArc(startPointX - 5, startPointY - 5, 10, 10, 180, 360);
        int endPointX = startPointX + (int) (Math.sin((double) Math.toRadians(alpha)) * w / 2);
        int endPointY = startPointY + (int) (Math.cos((double) Math.toRadians(alpha)) * h);
        double factorX = Math.sin((double) Math.toRadians(alpha - 90));
        double factorY = Math.cos((double) Math.toRadians(alpha + 90));
        for (int i = 0; i < 6; i++) {
            g.drawLine(startPointX + (int) (factorX * i), startPointY + (int) (factorY * i), endPointX, endPointY);
            g.drawLine(startPointX - (int) (factorX * i), startPointY - (int) (factorY * i), endPointX, endPointY);
        }
        String currentString = (new Float(Math.round(current * 10.0) / 10.0)).toString();
        g.setColor(new Color(255, 0, 0, 0.5f));
        g.drawString(currentString, x + w / 2 - g.getFont().getWidth(currentString) / 2, y + w / 4 - g.getFont().getLineHeight() / 2);

        g.setColor(lineColor);
    }

    /**
     * *
     * Set the player to start position
     */
    public void kickoff() {
        p1.getBody().setTransform(new Vec2((mittelpunkt.x - startX) / jBox2dFactor, mittelpunkt.y / jBox2dFactor), p1.getBody().getAngle());
        p2.getBody().setTransform(new Vec2((mittelpunkt.x + startX) / jBox2dFactor, mittelpunkt.y / jBox2dFactor), p2.getBody().getAngle());
        ball.getBody().setTransform(new Vec2(mittelpunkt.x / jBox2dFactor, mittelpunkt.y / jBox2dFactor), ball.getBody().getAngle());

        p1.getBody().setLinearVelocity(new Vec2(0, 0));
        p2.getBody().setLinearVelocity(new Vec2(0, 0));

        p1.setRotation(+90);
        p2.setRotation(-90);

        goalForP1 = false;
        goalForP2 = false;

        this.kickoffBall();

        if (GlobalSettings.sound) {
            airHorn.playAsSoundEffect(1.0f, 1.0f, false);
        }

        particleSystem[0].removeAllEmitters();
        particleSystem[1].removeAllEmitters();
    }

    /**
     * *
     * make the ball rolling to a rundom position
     */
    public void kickoffBall() {
        ball.rotate(random(0, 360));

        float hip = 10000;
        double rotation = Math.toRadians(ball.getRotation() - 90.f);
        Vec2 force = new Vec2((float) (hip * Math.cos(rotation)), (float) (hip * Math.sin(rotation)));
        //bodyBall.setLinearVelocity(force);
        ball.getBody().setLinearVelocity(force);

    }

    /**
     * Add a Fiction to the body, so that it gets slower
     *
     * @param b
     */
    private void makeFriction(Body b) {
        Vec2 newSpeed = b.m_force;
        newSpeed.x *= (GlobalSettings.reibung * GlobalSettings.reibung);
        newSpeed.y *= (GlobalSettings.reibung * GlobalSettings.reibung);
        //b.setLinearVelocity(newSpeed);
        b.applyForce(newSpeed, b.getWorldCenter());


    }

    /**
     * *
     * set the Position from the {@see Body} to the {@see GameObject}
     * @param b
     * @param go
     */
    private void updatePosition(Body b, GameObject go) {
        Vec2 position = b.getPosition();
        go.x = (int) (position.x * jBox2dFactor);
        go.y = (int) (position.y * jBox2dFactor);
    }

    /**
     * *
     * set the Position from the {@see Body} to the {@see GameObject} and add a constant to the new position
     * @param b
     * @param go
     * @param add
     */
    private void updatePosition(Body b, GameObject go, float add) {
        Vec2 position = b.getPosition();
        go.x = (int) (position.x * jBox2dFactor + add);
        go.y = (int) (position.y * jBox2dFactor + add);
    }

    /**
     * *
     * called, when leaving the game state
     *
     * @param gc
     * @param sbt
     */
    @Override
    public void leave(GameContainer gc, StateBasedGame sbt) {
        //bungabunga.stop();
        //airHorn.stop();
        //pop.stop();
    }

    /**
     * *
     * Draw the time with animated background
     *
     * @param g
     * @param x
     * @param y
     * @param w
     * @param h
     * @param currentTime
     */
    private void drawTime(Graphics g, int x, int y, int w, int h, int currentTime) {
        g.setColor(new Color(255, 0, 0, 0.5f));
        g.fillRect(x, y, w, h);
        if (!goldenGoal) {
            g.setColor(Color.white);
        } else if ((currentTime / 250) % 2 == 0) {
            g.setColor(Color.black);
        } else {
            g.setColor(Color.gray);
        }
        int wField = (int) (w * currentTime / GlobalSettings.gameRunningTime);
        if (wField > w) {
            wField = w;
        }
        g.fillRect(x, y, wField, h);
        g.setColor(Color.gray);
        String s;
        if ((time / 1000) % 60 < 10) {
            s = "Zeit " + (time / 60000) + " : 0" + (time / 1000) % 60;
        } else {
            s = "Zeit " + (time / 60000) + " : " + (time / 1000) % 60;
        }
        int textX = (int) (x + w / 2.0f - g.getFont().getWidth(s) / 2);
        int textY = (int) (y + h / 2.0f - g.getFont().getLineHeight() / 2);
        g.drawString(s, textX, textY);

    }

    /**
     * *
     * Create all Walls to the physicle world
     *
     * @param sizex
     * @param sizey
     * @param goalsizey
     */
    public void createWalls(float sizex, float sizey, float goalsizey) {

        addWall(mittelpunkt.x, mittelpunkt.y - (sizey / 2), (sizex / 2 + 1), 1); // Seitenlinie oben
        addWall(mittelpunkt.x, mittelpunkt.y + (sizey / 2), (sizex / 2 + 1), 1); // Seitenlinie unten

        float halfTorlinienLength = ((mittelpunkt.y - (goalsizey / 2)) - (mittelpunkt.y - (sizey / 2) + 25)) / 2;

        addWall(mittelpunkt.x - (sizex / 2) - 25, ((mittelpunkt.y - (sizey / 2) + 25) + halfTorlinienLength), 1, halfTorlinienLength);//Torlinie links oben
        addWall(mittelpunkt.x - (sizex / 2) - 25, ((mittelpunkt.y + (sizey / 2) - 25) - halfTorlinienLength), 1, halfTorlinienLength); // Torlinie links unten
        addWall(mittelpunkt.x + (sizex / 2) + 25, ((mittelpunkt.y - (sizey / 2) + 25) + halfTorlinienLength), 1, halfTorlinienLength); // Torlinie rechts oben
        addWall(mittelpunkt.x + (sizex / 2) + 25, ((mittelpunkt.y + (sizey / 2) - 25) - halfTorlinienLength), 1, halfTorlinienLength); // Torlinie rechts unten        
        addWall(mittelpunkt.x - (sizex / 2) - 65, mittelpunkt.y, 1, goalsizey); // Tornetz links
        addWall(mittelpunkt.x + (sizex / 2) + 65, mittelpunkt.y, 1, goalsizey); // Tornetz rechts       
        addWall(mittelpunkt.x - (sizex / 2) - 45, mittelpunkt.y - (goalsizey / 2), 20, 1); // Tornetz links oben
        addWall(mittelpunkt.x - (sizex / 2) - 45, mittelpunkt.y + (goalsizey / 2), 20, 1); // Tornetz links unten
        addWall(mittelpunkt.x + (sizex / 2) + 45, mittelpunkt.y - (goalsizey / 2), 20, 1); // Tornetz rechts oben
        addWall(mittelpunkt.x + (sizex / 2) + 45, mittelpunkt.y + (goalsizey / 2), 20, 1); // Tornetz rechts unten      
        addStaticEgde(mittelpunkt.x - (sizex / 2) - 25, mittelpunkt.y - (sizey / 2), 25.f, 25.f); // Ecken
        addStaticEgde(mittelpunkt.x - (sizex / 2) - 25, mittelpunkt.y + (sizey / 2 - 1), -25.f, 25.f);
        addStaticEgde(mittelpunkt.x + (sizex / 2) + 24, mittelpunkt.y + (sizey / 2 - 1), -25.f, -25.f);
        addStaticEgde(mittelpunkt.x + (sizex / 2) + 24, mittelpunkt.y - (sizey / 2), 25.f, -25.f);


    }

    /**
     * *
     * Draw the blanc field
     *
     * @param g
     * @param sizex
     * @param sizey
     * @param goalsizey
     */
    public void drawField(Graphics g, float sizex, float sizey, float goalsizey) {
        g.setColor(lineColor);
        g.setLineWidth(3);
        g.drawLine(mittelpunkt.x - (sizex / 2), mittelpunkt.y - (sizey / 2), mittelpunkt.x + (sizex / 2), mittelpunkt.y - (sizey / 2));//Seitenlinie oben
        g.drawLine(mittelpunkt.x - (sizex / 2), mittelpunkt.y + (sizey / 2), mittelpunkt.x + (sizex / 2), mittelpunkt.y + (sizey / 2));//Seitenlinie unten
        g.drawLine(mittelpunkt.x - (sizex / 2) - 25, mittelpunkt.y - (sizey / 2) + 25, mittelpunkt.x - (sizex / 2) - 25, mittelpunkt.y + (sizey / 2) - 25); // Seitenlinie links
        g.drawLine(mittelpunkt.x + (sizex / 2) + 25, mittelpunkt.y - (sizey / 2) + 25, mittelpunkt.x + (sizex / 2) + 25, mittelpunkt.y + (sizey / 2) - 25); // Seitenlinie rechts
        g.drawLine(mittelpunkt.x, mittelpunkt.y - (sizey / 2), mittelpunkt.x, mittelpunkt.y + (sizey / 2));
        g.drawRect(mittelpunkt.x - (sizex / 2) - 65, mittelpunkt.y - (goalsizey / 2), 40, goalsizey);//Tor links
        g.drawRect(mittelpunkt.x + (sizex / 2) + 25, mittelpunkt.y - (goalsizey / 2), 40, goalsizey);//Tor rechts
        g.drawLine(mittelpunkt.x - (sizex / 2) - 25, mittelpunkt.y - (sizey / 2) + 25, mittelpunkt.x - (sizex / 2), mittelpunkt.y - (sizey / 2)); // Ecken
        g.drawLine(mittelpunkt.x + (sizex / 2), mittelpunkt.y - (sizey / 2), mittelpunkt.x + (sizex / 2) + 25, mittelpunkt.y - (sizey / 2) + 25);
        g.drawLine(mittelpunkt.x - (sizex / 2) - 25, mittelpunkt.y + (sizey / 2) - 25, mittelpunkt.x - (sizex / 2), mittelpunkt.y + (sizey / 2));
        g.drawLine(mittelpunkt.x + (sizex / 2), mittelpunkt.y + (sizey / 2), mittelpunkt.x + (sizex / 2) + 25, mittelpunkt.y + (sizey / 2) - 25);
        g.drawOval(mittelpunkt.x - (0.15f * sizex), mittelpunkt.y - (0.15f * sizex), 0.3f * sizex, 0.3f * sizex);
        g.setLineWidth(11);
        g.drawLine(mittelpunkt.x, mittelpunkt.y, mittelpunkt.x, mittelpunkt.y);
        g.setLineWidth(1);
    }

    /**
     * *
     * Check if a goal happens
     */
    public void proofGoal() {

        int posX = ball.x;
        int posY = ball.y;

        if (posX < (mittelpunkt.x - (fieldSize.x / 2) - 42) && posY > (mittelpunkt.y - this.goalSize / 2) && posY < (mittelpunkt.y + this.goalSize / 2)) {
            this.goalForP2 = true;
        }

        if (posX > (mittelpunkt.x + (fieldSize.x / 2) + 25) && posY > (mittelpunkt.y - this.goalSize / 2) && posY < (mittelpunkt.y + this.goalSize / 2)) {
            this.goalForP1 = true;
        }

    }

    /**
     * *
     * Load a new map
     *
     * @param fileObj
     * @throws FileNotFoundException
     * @throws IOException
     */
    public void loadingMap(File fileObj) throws FileNotFoundException, IOException {

        BufferedReader reader = new BufferedReader(new FileReader(fileObj));
        String s;
        if ((s = reader.readLine()) != null) {
            fieldSize.x = Float.valueOf(s);
        }
        if ((s = reader.readLine()) != null) {
            fieldSize.y = Float.valueOf(s);
        }
        if ((s = reader.readLine()) != null) {
            this.goalSize = Integer.valueOf(s);
        }
        if ((s = reader.readLine()) != null) {
            this.numberOfPowerUp = Integer.valueOf(s);
        }
        if ((s = reader.readLine()) != null) {
            this.numberOfPowerDown = Integer.valueOf(s);
        }
        if ((s = reader.readLine()) != null) {
            int blue = 0;
            int green = 0;
            int red = 0;
            blue = Integer.valueOf(s);
            if ((s = reader.readLine()) != null) {
                green = Integer.valueOf(s);
                if ((s = reader.readLine()) != null) {
                    red = Integer.valueOf(s);
                }
            }
            this.background = new Color(red, green, blue);
        }
        if ((s = reader.readLine()) != null) {
            int blue = 0;
            int green = 0;
            int red = 0;
            blue = Integer.valueOf(s);
            if ((s = reader.readLine()) != null) {
                green = Integer.valueOf(s);
                if ((s = reader.readLine()) != null) {
                    red = Integer.valueOf(s);
                }
            }
            this.lineColor = new Color(red, green, blue);
        }
        int i = 0;
        while ((s = reader.readLine()) != null) {
            int value = 0;
            for (int j = 0; j < s.length(); j++) {
                if (s.charAt(j) == 48) {
                    value = 0;
                } else {
                    value = 1;
                }
                this.map[i][j] = value;
            }
            i++;
        }
    }
}
